/*------------------------------------------------------*/
/* class declaration for Client Rate Controller         */
/*                                                      */
/* InfoClientRateController.h                           */
/*                                                      */
/* Copyright (C) CyberNaut.com.cn			            */
/* All rights reserved                                  */
/*                                                      */
/* Author                                               */
/*    Quark zhou (quark.zhou@cybernaut.com.cn)          */
/*                                                      */
/* History                                              */
/*    03/23/2006  Create                                */
/*                                                      */
/*------------------------------------------------------*/
#ifndef __INFO_CLIENT_RATE_CONTROLLER_H_H__
#define __INFO_CLIENT_RATE_CONTROLLER_H_H__

#include "CmBase.h"
#include "CmThreadInterface.h"
#include "CmThread.h"
#include "CmConnectionInterface.h"
#include "InfoSessionApiDefine.h"
#include "InfoDataBuffer.h"
#include "CmMessageBlock.h"
#include "connprovider.h"

#if defined _INFO_TIMER_
#include "Mmsystem.h"
#pragma comment( lib, "Winmm.lib")
#else
class CMMRateThread;
#endif

#if defined _INFO_TIMER_
#include "CmMutex.h"
#endif

class CMMDataBuffer;
class CMMRateController;
#if !defined _INFO_TIMER_
class CMMSendEvent;
#endif //_MM_MUTEX

const DWORD g_dwAudioMemSize = 512 * 2;
const DWORD g_dwVideoMemSize = 1024 * 2;
const DWORD g_dwMaxAudioSize = 15;
const DWORD g_dwMaxVideoSize = 60;

class IAVSession;

class CM_OS_EXPORT CInfoRateController
{
public:
	static CInfoRateController * Instance( );
	~CInfoRateController( );
	enum { // in bps
		BW1K	= 1024,
		BW30K	= 30720,
		BW50K	= 51200,
		BW80K	= 81920,
		BW100K	= 102400,
		BW200K	= 204800,
		BW300K	= 307200,
		BW400K	= 409600,
		BW800K	= 819200
	};
public:
	// Up layer Interface, called from the main thread or the sending threads
	CmResult SetTransport( DATAFLAG dataFlag, 
			IConnection* pConn);
	CmResult SendData( DATAFLAG dataFlag,
			DATA_Priority Priority,
			CCmMessageBlock& aData);
	CmResult SetBandWidth( DWORD dwBandWidth);
	CmResult StartSend( );
	CmResult StopSend( );
// 	void SetInSameMcs( BOOL bInSame, ICmTransport * pTrans);
public:
	// Rate thread Interface, called from the Timer thread or the Rate thread
	// schedule next time to send data according to current bandwidth
	UINT ScheduleNextSendingTimer( );
	// call m_pTransport to send data, return TRUE if video data is sent
	BOOL DeliveryData( );

#if !defined _INFO_TIMER_
	CmResult PostSendEvent( );	
#endif // !_MM_MUTEX
#if !defined _INFO_TIMER_
	UINT GetMinInterval( ) {
		return( m_uMinInterval);
	}
#endif
private:
	static CInfoRateController *	s_pRateController;
	IConnection*					m_pAudioTransport;
	IConnection*					m_pVideoTransport;
	// audio data will be sent first, if failed, then be put into the buffer
	CInfoDataBuffer					m_AudioDataBuffer;
	// video data will be put into the buffer directly, then be sent by the network bandwidth
	CInfoDataBuffer					m_VideoDataBuffer;
	// current bandwidth, in bits per second
	DWORD							m_dwBandWidth;
	//
	DWORD							m_dwAudioBand;
	// current Video packet size
	DWORD							m_dwPacketSize;
private:
#if defined _INFO_TIMER_
	// the min resolution of the multimedia timer
	UINT							m_uMinResolution;		
	UINT							m_uSendTimerId;
	UINT							m_cTimerCount;
	UINT							m_cRateCount;
	UINT							m_cTimeOut;
#else
	// use own thread
	CMMRateThread *					m_pRateThread;
	UINT							m_uMinInterval;
#endif
#if defined _INFO_TIMER_
	CCmMutexThread					m_Mutex;
#else
	// use post event
	ACmThread *						m_pCurrent;
	BOOL							m_bEmpty;
#endif
	// Only enable SmoothSend when uses UDP
	BOOL							m_bEnabled;
private:
	CInfoRateController( );
	CInfoRateController( const CInfoRateController&);
	CInfoRateController& operator= ( const CInfoRateController&);
};

#if !defined _INFO_MUTEX_
class CInfoSendEvent : public ICmEvent
{
public:
	CInfoSendEvent( CInfoRateController * pController);
	virtual ~CInfoSendEvent( ) { };
	// from ICmEvent
	CmResult OnEventFire( );
private:
	CInfoRateController *				m_pController;
};
#endif // !_MM_MUTEX

#if defined _INFO_TIMER_
extern void CALLBACK InfoTimeProc( UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2);
#endif

#endif //__INFO_CLIENT_RATE_CONTROLLER_H_H__

